/**
 * 图像分析服务
 * 负责分析图片内容，检测敏感信息和不适当的内容
 */
const fs = require('fs');
const path = require('path');
const sharp = require('sharp');
const tesseract = require('node-tesseract-ocr');
const crypto = require('crypto-js');
const logger = require('../utils/logger');
const { Setting } = require('../models');

// 默认配置
const defaultSettings = {
  // 图片过滤级别
  filteringLevel: 'medium', // low, medium, high
  
  // OCR识别设置
  enableOCR: true,
  
  // 敏感内容类型
  sensitiveContentTypes: [
    'adult',
    'violence',
    'text-with-numbers',
    'personal-document'
  ],
  
  // 预定义的NSFW检测阈值
  nsfwThresholds: {
    low: 0.8,    // 低：只过滤高可信度的不良内容
    medium: 0.6, // 中：过滤中等可信度的不良内容
    high: 0.4    // 高：过滤任何有潜在不良内容的图片
  },
  
  // OCR敏感内容关键词
  ocrSensitiveKeywords: [
    '身份证',
    '信用卡',
    '银行卡',
    '密码',
    '账号'
  ],
  
  // 图片哈希黑名单
  blacklistedHashes: []
};

// 当前配置
let currentSettings = { ...defaultSettings };

// Tesseract OCR配置
const tesseractConfig = {
  lang: 'chi_sim+eng', // 中文简体和英文
  oem: 1,  // 使用LSTM神经网络
  psm: 3,  // 自动分页检测
  dpi: 300,
  load_system_dawg: 0,
  load_freq_dawg: 0,
  debug_file: path.join(__dirname, '../../logs/tesseract.log'),
};

/**
 * 初始化图片分析服务
 */
const initialize = async () => {
  try {
    // 从数据库加载设置
    const settings = await Setting.findOne({ key: 'imageAnalysisSettings' });
    
    if (settings && settings.value) {
      currentSettings = { ...defaultSettings, ...JSON.parse(settings.value) };
    }
    
    logger.info('图片分析服务已初始化');
    return true;
  } catch (error) {
    logger.error('初始化图片分析服务失败:', error);
    return false;
  }
};

/**
 * 获取当前图像分析设置
 */
const getSettings = () => {
  return { ...currentSettings };
};

/**
 * 更新图片分析设置
 */
const updateSettings = async (newSettings) => {
  try {
    const mergedSettings = { ...currentSettings, ...newSettings };
    
    // 保存到数据库
    await Setting.upsert({
      key: 'imageAnalysisSettings',
      value: JSON.stringify(mergedSettings)
    });
    
    // 更新当前设置
    currentSettings = mergedSettings;
    
    return { success: true };
  } catch (error) {
    logger.error('更新图片分析设置失败:', error);
    return { success: false, error: error.message };
  }
};

/**
 * 计算图片哈希
 * 使用perceptual hash算法，即使图片经过轻微修改，哈希值也基本相同
 */
const calculateImageHash = async (imagePath) => {
  try {
    // 使用sharp调整图片大小为8x8并转为灰度，然后计算感知哈希
    const { data, info } = await sharp(imagePath)
      .resize(8, 8, { fit: 'fill' })
      .grayscale()
      .raw()
      .toBuffer({ resolveWithObject: true });
    
    // 计算DCT（离散余弦变换）
    const pixelValues = Array.from(data);
    const mean = pixelValues.reduce((sum, val) => sum + val, 0) / pixelValues.length;
    
    // 生成哈希字符串（64位）
    let hashString = '';
    for (const value of pixelValues) {
      hashString += value >= mean ? '1' : '0';
    }
    
    // 转为16进制字符串
    const hashHex = parseInt(hashString, 2).toString(16).padStart(16, '0');
    return hashHex;
  } catch (error) {
    logger.error('计算图像哈希失败:', error);
    return null;
  }
};

/**
 * 从图片中提取文本（OCR）
 */
const extractTextFromImage = async (imagePath) => {
  if (!currentSettings.enableOCR) {
    return { success: false, message: 'OCR功能已禁用' };
  }
  
  try {
    // 使用sharp优化图片以提高OCR准确性
    const optimizedImagePath = path.join(
      path.dirname(imagePath),
      `optimized_${path.basename(imagePath)}`
    );
    
    await sharp(imagePath)
      .resize(1200, 1200, { fit: 'inside' })
      .sharpen()
      .normalize()
      .toFile(optimizedImagePath);
    
    // 使用Tesseract执行OCR
    const text = await tesseract.recognize(optimizedImagePath, tesseractConfig);
    
    // 清理临时文件
    fs.unlinkSync(optimizedImagePath);
    
    return {
      success: true,
      text: text.trim()
    };
  } catch (error) {
    logger.error('OCR文本提取失败:', error);
    return {
      success: false,
      message: '文本提取失败',
      error: error.message
    };
  }
};

/**
 * 检查OCR文本中的敏感内容
 */
const checkSensitiveTextContent = (text) => {
  if (!text) return { hasSensitiveContent: false };
  
  const result = {
    hasSensitiveContent: false,
    matches: []
  };
  
  // 使用共享工具检测敏感内容
  const sensitiveContentUtils = require('../utils/sensitiveContentUtils');
  const sensitiveContentCheck = sensitiveContentUtils.detectSensitiveContent(text, currentSettings);
  
  if (sensitiveContentCheck.hasSensitiveContent) {
    result.hasSensitiveContent = true;
    
    // 合并检测结果
    if (sensitiveContentCheck.numberDetection.isSensitive) {
      result.matches.push(...sensitiveContentCheck.numberDetection.matches);
    }
    
    if (sensitiveContentCheck.keywordDetection.isSensitive) {
      result.matches.push(...sensitiveContentCheck.keywordDetection.matches);
    }
  }
  
  // 还可以检查关键词
  for (const keyword of currentSettings.ocrSensitiveKeywords) {
    if (text.toLowerCase().includes(keyword.toLowerCase())) {
      result.hasSensitiveContent = true;
      result.matches.push(keyword);
    }
  }
  
  return result;
};

/**
 * 模拟NSFW内容检测
 * 注意：此函数是模拟的。在实际生产环境中，应集成实际的机器学习模型或云API服务
 * 可选的实现方式：
 * 1. 使用TensorFlow.js和预训练的NSFW模型
 * 2. 使用Google Cloud Vision API
 * 3. 使用AWS Rekognition
 * 4. 使用自定义的机器学习模型
 */
const detectNSFWContent = async (imagePath) => {
  try {
    logger.info(`正在分析图片 ${imagePath} 中的NSFW内容`);
    
    // 计算图片哈希
    const imageHash = await calculateImageHash(imagePath);
    
    // 检查哈希黑名单
    if (imageHash && currentSettings.blacklistedHashes.includes(imageHash)) {
      return {
        isNSFW: true,
        score: 1.0,
        reason: 'hash_blacklisted'
      };
    }
    
    // 模拟分析结果
    // 在实际实现中，这里应该调用实际的AI模型
    const simulatedCategories = {
      adult: Math.random() * 0.3,
      violence: Math.random() * 0.2,
      racy: Math.random() * 0.4,
      medical: Math.random() * 0.1,
      normal: Math.random() * 0.8
    };
    
    // 确定NSFW阈值
    const threshold = currentSettings.nsfwThresholds[currentSettings.filteringLevel] || 0.6;
    
    // 检查是否任何敏感类别超过阈值
    const maxCategory = Object.entries(simulatedCategories).reduce(
      (max, [category, score]) => (score > max.score ? { category, score } : max),
      { category: 'normal', score: 0 }
    );
    
    const isNSFW = maxCategory.category !== 'normal' && maxCategory.score > threshold;
    
    return {
      isNSFW,
      score: maxCategory.score,
      category: maxCategory.category,
      reason: isNSFW ? `detected_${maxCategory.category}` : 'safe',
      imageHash
    };
  } catch (error) {
    logger.error('NSFW内容检测失败:', error);
    
    // 在出错时，默认为安全（避免误判）
    return {
      isNSFW: false,
      score: 0,
      reason: 'detection_error',
      error: error.message
    };
  }
};

/**
 * 主要的图片分析函数
 */
const analyzeImage = async (imagePath) => {
  try {
    logger.info(`开始分析图片: ${imagePath}`);
    
    const result = {
      isAllowed: true,
      reasons: [],
      hasSensitiveText: false,
      hasNSFWContent: false,
      textContent: '',
      confidenceScore: 0,
      imageHash: null
    };
    
    // 1. 检查图片大小和格式
    const stats = fs.statSync(imagePath);
    const fileSizeMB = stats.size / (1024 * 1024);
    
    // 获取图片基本信息
    const metadata = await sharp(imagePath).metadata();
    
    // 记录图片信息
    result.metadata = {
      width: metadata.width,
      height: metadata.height,
      format: metadata.format,
      size: fileSizeMB.toFixed(2) + ' MB'
    };
    
    // 2. 计算图片哈希
    result.imageHash = await calculateImageHash(imagePath);
    
    // 3. 检查NSFW内容
    const nsfwResult = await detectNSFWContent(imagePath);
    if (nsfwResult.isNSFW) {
      result.isAllowed = false;
      result.hasNSFWContent = true;
      result.reasons.push(`敏感内容 (${nsfwResult.category}, 置信度: ${nsfwResult.score.toFixed(2)})`);
      result.confidenceScore = nsfwResult.score;
    }
    
    // 4. OCR提取和检查文本
    if (currentSettings.enableOCR) {
      const ocrResult = await extractTextFromImage(imagePath);
      
      if (ocrResult.success) {
        result.textContent = ocrResult.text;
        
        // 检查提取的文本中是否有敏感内容
        const sensitiveTextCheck = checkSensitiveTextContent(result.textContent);
        
        if (sensitiveTextCheck.hasSensitiveContent) {
          result.isAllowed = false;
          result.hasSensitiveText = true;
          result.reasons.push(`敏感文本: ${sensitiveTextCheck.matches.join(', ')}`);
        }
      }
    }
    
    // 记录分析结果
    if (!result.isAllowed) {
      logger.warn('图片包含敏感内容，已被拦截', {
        imagePath,
        reasons: result.reasons,
        hash: result.imageHash
      });
      
      // 如果是确认的不良内容，添加到黑名单
      if (result.hasNSFWContent && result.confidenceScore > 0.8 && result.imageHash) {
        // 更新黑名单
        if (!currentSettings.blacklistedHashes.includes(result.imageHash)) {
          currentSettings.blacklistedHashes.push(result.imageHash);
          await updateSettings({ blacklistedHashes: currentSettings.blacklistedHashes });
        }
      }
    }
    
    return result;
  } catch (error) {
    logger.error('图片分析失败:', error);
    
    // 在出错时，根据配置决定是否允许通过
    const isAllowed = currentSettings.filteringLevel !== 'high';
    
    return {
      isAllowed,
      reasons: isAllowed ? [] : ['分析过程出错，根据当前高级别过滤策略，默认拦截'],
      error: error.message
    };
  }
};

module.exports = {
  initialize,
  getSettings,
  updateSettings,
  calculateImageHash,
  extractTextFromImage,
  detectNSFWContent,
  analyzeImage
}; 